
{***********************************************************}
{                                                           }
{      Informix Data Access Components                      }
{                                                           }
{      Informix Native Fields                               }
{                                                           }
{      Copyright (c) 2001-2008 Luxena Software Company      }
{      http://www.luxena.com                                }
{      e-mail: support@luxena.com                           }
{                                                           }
{***********************************************************}

unit IfxNativeFields;

{$I lx.inc}

interface

uses
  SysUtils, Classes, Graphics, DB, LXClasses, LXDBTypes, IfxTypes, IfxDecimal,
  IfxDateTime, IfxLocator, IfxInt8, IfxLob, IfxValues;


type

{ Enumerations }

  TIfxTimeUnit = (tuYear, tuMonth, tuDay, tuHour, tuMinute, tuSecond, tuFrac1,
    tuFrac2, tuFrac3, tuFrac4, tuFrac5);


const

{ Property Default Values }

  IFX_DEFAULT_STRING_SIZE = 20;
  IFX_DEFAULT_NUMERIC_ALIGNMENT = taRightJustify;
  IFX_DEFAULT_DECIMAL_PRECISION = 16;
  IFX_DEFAULT_DECIMAL_SCALE = -1;
  IFX_DEFAULT_DTIME_FIRST = tuYear;
  IFX_DEFAULT_DTIME_LAST = tuFrac3;

  IFX_DEFAULT_MONEY_DISPLAY_FORMAT: string = '$<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<.## @';
  IFX_DEFAULT_MONEY_EDIT_FORMAT: string = '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<.##';


type

{ TIfxNativeField }

  TIfxNativeField = class(TField, IIfxValue, IIfxValueBufferProvider)
  private
    FValue: TIfxFieldValue;
    FTempBuffer: PChar;

  protected
    procedure SetDataSet(ADataSet: TDataSet); override;

    function CreateValue: TIfxFieldValue; virtual; abstract;
    function GetValue: TIfxFieldValue;
    function ActiveValue: TIfxValue;
    function DataReadBuffer: PChar;
    function DataWriteBuffer: PChar;
    procedure Validate(Buffer: Pointer);
    function ResetSubject: TLXDelegat;
    procedure NotifyChange;

    function GetDataSize: Integer; override;
    
    function GetAsBCD: TBcd; {$IFDEF D6}override;{$ENDIF}
    function GetAsBoolean: Boolean; override;
    function GetAsByte: TBlobByteData;
    function GetAsCurrency: Currency; override;
    function GetAsDate: int4;
    function GetAsDateTime: TDateTime; override;
    function GetAsDecimal: TDecimal;
    function GetAsDTime: TDTime;
    function GetAsFloat: Double; override;
    function GetAsInt8: TIfx_int8;
    function GetAsInteger: LongInt; override;
    function GetAsInterval: TIntrvl;
    function GetAsLargeint: Largeint;
    function GetAsLob: IIfxLob;
    function GetAsLocator: PLoc;
    function GetAsSmallFloat: Single;
    function GetAsSmallInt: int2;
    function GetAsSQLTimeStamp: TSQLTimeStamp; {$IFDEF D6}override;{$ENDIF}
    function GetAsString: string; override;
    function GetAsTime: TDateTime;
    function GetAsVariant: Variant; override;
    procedure GetText(var Text: string; DisplayText: Boolean); override;

    procedure SetNull;
    procedure SetAsBCD(const Value: TBcd); {$IFDEF D6}override;{$ENDIF}
    procedure SetAsBlob(const Value: IIfxLob);
    procedure SetAsBoolean(Value: Boolean); override;
    procedure SetAsByte(const Value: TBlobByteData);
    procedure SetAsChar(const Value: string);
    procedure SetAsClob(const Value: IIfxLob);
    procedure SetAsCurrency(Value: Currency); override;
    procedure SetAsDate(Value: int4);
    procedure SetAsDateTime(Value: TDateTime); override;
    procedure SetAsDecimal(const Value: TDecimal);
    procedure SetAsDTime(const Value: TDTime);
    procedure SetAsFloat(Value: Double); override;
    procedure SetAsInt8(const Value: TIfx_int8);
    procedure SetAsInteger(Value: LongInt); override;
    procedure SetAsInterval(const Value: TIntrvl);
    procedure SetAsLargeint(Value: Largeint);
    procedure SetAsLocator(Value: PLoc);
    procedure SetAsLVarChar(const Value: string);
    procedure SetAsMoney(const Value: TDecimal);
    procedure SetAsNChar(const Value: string);
    procedure SetAsNVarChar(const Value: string);
    procedure SetAsOpaque(const Value: string);
    procedure SetAsSmallFloat(Value: Single);
    procedure SetAsSmallInt(Value: int2);
    procedure SetAsSQLTimeStamp(const Value: TSQLTimeStamp); {$IFDEF D6}override;{$ENDIF}
    procedure SetAsString(const Value: string); override;
    procedure SetAsText(const Value: string);
    procedure SetAsTime(Value: TDateTime);
    procedure SetAsVarChar(const Value: string);
    procedure SetVarValue(const Value: Variant); override;

  public
    destructor Destroy; override;

{$IFNDEF D6}
    property AsBCD: TBcd read GetAsBCD write SetAsBCD;
{$ENDIF}
    property AsBlob: IIfxLob read GetAsLob write SetAsBlob;
    property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean;
    property AsByte: TBlobByteData read GetAsByte write SetAsByte;
    property AsChar: string read GetAsString write SetAsChar;
    property AsClob: IIfxLob read GetAsLob write SetAsClob;
    property AsDate: int4 read GetAsDate write SetAsDate;
    property AsDecimal: TDecimal read GetAsDecimal write SetAsDecimal;
    property AsDTime: TDTime read GetAsDTime write SetAsDTime;
    property AsInt8: TIfx_int8 read GetAsInt8 write SetAsInt8;
    property AsInterval: TIntrvl read GetAsInterval write SetAsInterval;
    property AsLargeint: Largeint read GetAsLargeint write SetAsLargeint;
    property AsLob: IIfxLob read GetAsLob;
    property AsLocator: PLoc read GetAsLocator write SetAsLocator;
    property AsLVarChar: string read GetAsString write SetAsLVarChar;
    property AsMoney: TDecimal read GetAsDecimal write SetAsMoney;
    property AsNChar: string read GetAsString write SetAsNChar;
    property AsNVarChar: string read GetAsString write SetAsNVarChar;
    property AsOpaque: string read GetAsString write SetAsOpaque;
    property AsSmallFloat: Single read GetAsSmallFloat write SetAsSmallFloat;
    property AsSmallInt: int2 read GetAsSmallInt write SetAsSmallInt;
{$IFNDEF D6}
    property AsSQLTimeStamp: TSQLTimeStamp read GetAsSQLTimeStamp write SetAsSQLTimeStamp;
{$ENDIF}
    property AsText: string read GetAsString write SetAsText;
    property AsTime: TDateTime read GetAsTime write SetAsTime;
    property AsVarChar: string read GetAsString write SetAsVarChar;

    function Format(const FmtStr: string): string;

    procedure Assign(Source: TPersistent); override;
    procedure AssignValue(const Value: IIfxValue);
    procedure AssignToValue(const Value: IIfxValue);

    procedure SaveToStream(Stream: TStream);
    procedure SaveToFile(const FileName: string);
    procedure LoadFromStream(Stream: TStream);
    procedure LoadFromFile(const FileName: string);

    procedure CopyValue(const Value: IIfxValue; var Buffer);
  end;


{ TIfxStringField }

  TIfxStringField = class(TIfxNativeField)
  protected
    class procedure CheckTypeSize(Value: Integer); override;
    function GetDataSize: Integer; override;
    function GetDefaultWidth: Integer; override;
    procedure GetText(var Text: string; DisplayText: Boolean); override;
    procedure SetAsString(const Value: string); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: string read GetAsString write SetAsString;
  published
    property EditMask;
    property Size default IFX_DEFAULT_STRING_SIZE;
  end;


{ TIfxCharField }

  TIfxCharField = class(TIfxStringField)
  protected
    function CreateValue: TIfxFieldValue; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;


{ TIfxFormatableField }

  TIfxFormatableField = class(TIfxNativeField)
  private
    FDisplayFormat: string;
    FEditFormat: string;
    procedure SetDisplayFormat(const Value: string);
    procedure SetEditFormat(const Value: string);
  protected
    procedure GetText(var Text: string; DisplayText: Boolean); override;
  published
    property DisplayFormat: string read FDisplayFormat write SetDisplayFormat;
    property EditFormat: string read FEditFormat write SetEditFormat;
  end;


{ TIfxNumericField }

  TIfxNumericField = class(TIfxFormatableField)
  public
    constructor Create(AOwner: TComponent); override;
  published
    property Alignment default IFX_DEFAULT_NUMERIC_ALIGNMENT;
  end;


{ TIfxSmallIntField }

  TIfxSmallIntField = class(TIfxNumericField)
  protected
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: SmallInt read GetAsSmallInt write SetAsSmallInt;
  end;


{ TIfxIntegerField }

  TIfxIntegerField = class(TIfxNumericField)
  protected
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: Integer read GetAsInteger write SetAsInteger;
  end;


{ TIfxFloatField }

  TIfxFloatField = class(TIfxNumericField)
  protected
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: Double read GetAsFloat write SetAsFloat;
  end;


{ TIfxSmallFloatField }

  TIfxSmallFloatField = class(TIfxNumericField)
  protected
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: Single read GetAsSmallFloat write SetAsSmallFloat;
  end;

  
{ TIfxDecimalField }

  TIfxDecimalField = class(TIfxNumericField)
  private
    class function AdjustScale(Value: Integer; DisplayValue: Boolean): Integer;
    function GetPrecision: Integer;
    function GetScale: Integer;
    procedure SetPrecision(Value: Integer);
    procedure SetScale(Value: Integer);
  protected
    class procedure CheckTypeSize(Value: Integer); override;
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: TDecimal read GetAsDecimal write SetAsDecimal;
  published
    property Precision: Integer read GetPrecision write SetPrecision default IFX_DEFAULT_DECIMAL_PRECISION;
    property Scale: Integer read GetScale write SetScale default IFX_DEFAULT_DECIMAL_SCALE;
  end;


{ TIfxSerialField }

  TIfxSerialField = class(TIfxIntegerField)
  public
    constructor Create(AOwner: TComponent); override;
  end;


{ TIfxDateField }

  TIfxDateField = class(TIfxFormatableField)
  protected
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: int4 read GetAsDate write SetAsDate;
  end;


{ TIfxMoneyField }

  TIfxMoneyField = class(TIfxDecimalField)
  protected                                                             
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure GetText(var Text: string; DisplayText: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
  end;
  

{ TIfxTimeField }

  TIfxTimeField = class(TIfxFormatableField)
  private
    function GetFirstUnit: TIfxTimeUnit;
    function GetLastUnit: TIfxTimeUnit;
  protected
    class procedure CheckTypeSize(Value: Integer); override;
    function GetDefaultWidth: Integer; override;
    procedure SetFirstUnit(const Value: TIfxTimeUnit); virtual; abstract;
    procedure SetLastUnit(const Value: TIfxTimeUnit); virtual; abstract;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property FirstUnit: TIfxTimeUnit read GetFirstUnit write SetFirstUnit;
    property LastUnit: TIfxTimeUnit read GetLastUnit write SetLastUnit;
  end;


{ TIfxDateTimeField }

  TIfxDateTimeField = class(TIfxTimeField)
  protected
    function CreateValue: TIfxFieldValue; override;
    procedure CopyData(Source, Dest: Pointer); override;
    procedure SetFirstUnit(const Value: TIfxTimeUnit); override;
    procedure SetLastUnit(const Value: TIfxTimeUnit); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: TDTime read GetAsDTime write SetAsDTime;
  published
    property FirstUnit default IFX_DEFAULT_DTIME_FIRST;
    property LastUnit default IFX_DEFAULT_DTIME_LAST;
  end;


{ TIfxVarCharField }

  TIfxVarCharField = class(TIfxStringField)
  protected
    function CreateValue: TIfxFieldValue; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;


{ TIfxIntervalField }

  TIfxIntervalField = class(TIfxTimeField)
  private
    function GetPrecision: Integer;
    procedure SetPrecision(const Value: Integer);
  protected
    function CreateValue: TIfxFieldValue; override;
    procedure CopyData(Source, Dest: Pointer); override;
    procedure SetFirstUnit(const Value: TIfxTimeUnit); override;
    procedure SetLastUnit(const Value: TIfxTimeUnit); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: TIntrvl read GetAsInterval write SetAsInterval;
  published
    property Precision: Integer read GetPrecision write SetPrecision default 3;
    property FirstUnit default tuDay;
    property LastUnit default tuFrac3;
  end;


{ TIfxNCharField }

  TIfxNCharField = class(TIfxCharField)
  protected
    function CreateValue: TIfxFieldValue; override;
  end;


{ TIfxNVarCharField }

  TIfxNVarCharField = class(TIfxVarCharField)
  protected
    function CreateValue: TIfxFieldValue; override;
  end;


{ TIfxInt8Field }

  TIfxInt8Field = class(TIfxNumericField)
  protected
    function CreateValue: TIfxFieldValue; override;
    function GetDefaultWidth: Integer; override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: TIfx_int8 read GetAsInt8 write SetAsInt8;
  end;


{ TIfxLVarCharField }

  TIfxLVarCharField = class(TIfxVarCharField)
  protected
    function CreateValue: TIfxFieldValue; override;
  end;


{ TIfxLobField }

  TIfxLobField = class(TIfxNativeField)
  private
    procedure LoadFromBitmap(Bitmap: TBitmap);
    procedure LoadFromStrings(Strings: TStrings);
    procedure SaveToBitmap(Bitmap: TBitmap);
    procedure SaveToStrings(Strings: TStrings);
  protected
    procedure AssignTo(Dest: TPersistent); override;
    procedure CopyData(Source, Dest: Pointer); override;
  public
    class function IsBlob: Boolean; override;
    procedure Assign(Source: TPersistent); override;
    property Value: IIfxLob read GetAsLob;
  end;


{ TIfxBlobField }

  TIfxBlobField = class(TIfxLobField)
  protected
    function CreateValue: TIfxFieldValue; override;
    procedure GetText(var Text: string; DisplayText: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: IIfxLob read GetAsLob write SetAsBlob;
  end;


{ TIfxClobField }

  TIfxClobField = class(TIfxLobField)
  protected
    function CreateValue: TIfxFieldValue; override;
    procedure GetText(var Text: string; DisplayText: Boolean); override;
  public
    constructor Create(AOwner: TComponent); override;
    property Value: IIfxLob read GetAsLob write SetAsClob;
  end;


implementation

uses DBConsts, LXTypes, LXSysUtils, IfxConsts, Ifx, IfxConvert, IfxConnection,
  IfxCustomDataSet;


{ TIfxNativeField }

destructor TIfxNativeField.Destroy;
begin
  FValue.Free;
  inherited;
end;

procedure TIfxNativeField.SetDataSet(ADataSet: TDataSet);
begin
  if ADataSet <> DataSet then
    if ADataSet is TIfxCustomDataSet then
      inherited else
      IDACError(SInvalidFieldDataSet, Self);
end;

function TIfxNativeField.GetValue: TIfxFieldValue;
begin
  if FValue = nil then
    FValue := CreateValue;
  Result := FValue;
end;

function TIfxNativeField.ActiveValue: TIfxValue;
begin
  if IsNull then
    Result := TIfxNullValue.Instance else
    Result := GetValue;
end;

function TIfxNativeField.DataReadBuffer: PChar;
begin
  Result := FTempBuffer;
  if Result = nil then
    Result := TIfxCustomDataSet(DataSet).FieldDataReadBuffer(Self);
end;

function TIfxNativeField.DataWriteBuffer: PChar;
begin
  Result := FTempBuffer;
  if Result = nil then
    Result := TIfxCustomDataSet(DataSet).FieldDataWriteBuffer(Self);
end;

procedure TIfxNativeField.Validate(Buffer: Pointer);
begin
  if FTempBuffer = nil then
  begin
    FTempBuffer := Buffer;
    try
      inherited Validate(Buffer);
    finally
      FTempBuffer := nil;
    end;
  end;
end;

function TIfxNativeField.ResetSubject: TLXDelegat;
begin
  Result := nil;
end;

procedure TIfxNativeField.NotifyChange;
begin
  if FTempBuffer = nil then
    TIfxCustomDataSet(DataSet).NotifyFieldChange(Self);
end;

function TIfxNativeField.GetDataSize: Integer;
begin
  Result := GetValue.BufferSize;
end;

function TIfxNativeField.GetAsBCD: TBcd;
begin
  Result := ActiveValue.AsBCD;
end;

function TIfxNativeField.GetAsBoolean: Boolean;
begin
  Result := ActiveValue.AsBoolean;
end;

function TIfxNativeField.GetAsByte: TBlobByteData;
begin
  Result := ActiveValue.AsByte;
end;

function TIfxNativeField.GetAsCurrency: Currency;
begin
  Result := ActiveValue.AsCurrency;
end;

function TIfxNativeField.GetAsDate: int4;
begin
  Result := ActiveValue.AsDate;
end;

function TIfxNativeField.GetAsDateTime: TDateTime;
begin
  Result := ActiveValue.AsDateTime;
end;

function TIfxNativeField.GetAsDecimal: TDecimal;
begin
  Result := ActiveValue.AsDecimal;
end;

function TIfxNativeField.GetAsDTime: TDTime;
begin
  Result := ActiveValue.AsDTime;
end;

function TIfxNativeField.GetAsFloat: Double;
begin
  Result := ActiveValue.AsFloat;
end;

function TIfxNativeField.GetAsInt8: TIfx_int8;
begin
  Result := ActiveValue.AsInt8;
end;

function TIfxNativeField.GetAsInteger: Longint;
begin
  Result := ActiveValue.AsInteger;
end;

function TIfxNativeField.GetAsInterval: TIntrvl;
begin
  Result := ActiveValue.AsInterval;
end;

function TIfxNativeField.GetAsLargeint: Largeint;
begin
  Result := ActiveValue.AsLargeint;
end;

function TIfxNativeField.GetAsLob: IIfxLob;
begin
  Result := ActiveValue.AsLob;
end;

function TIfxNativeField.GetAsLocator: PLoc;
begin
  Result := ActiveValue.AsLocator;
end;

function TIfxNativeField.GetAsSmallFloat: Single;
begin
  Result := ActiveValue.AsSmallFloat;
end;

function TIfxNativeField.GetAsSmallInt: int2;
begin
  Result := ActiveValue.AsSmallInt;
end;

function TIfxNativeField.GetAsSQLTimeStamp: TSQLTimeStamp;
begin
  Result := ActiveValue.AsSQLTimeStamp;
end;

function TIfxNativeField.GetAsString: string;
begin
  Result := ActiveValue.AsString;
end;

function TIfxNativeField.GetAsTime: TDateTime;
begin
  Result := ActiveValue.AsTime;
end;

function TIfxNativeField.GetAsVariant: Variant;
begin
  Result := ActiveValue.AsVariant;
end;

procedure TIfxNativeField.GetText(var Text: string; DisplayText: Boolean);
begin
  try
    Text := AsString;
  except
    on E: Exception do
      Text := E.Message;
  end;
end;

function TIfxNativeField.Format(const FmtStr: string): string;
begin
  Result := ActiveValue.Format(FmtStr);
end;

procedure TIfxNativeField.SetNull;
begin
  if FTempBuffer = nil then Clear;
end;

procedure TIfxNativeField.SetAsBCD(const Value: TBcd);
begin
  GetValue.AsBCD := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsBlob(const Value: IIfxLob);
begin
  GetValue.AsLob := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsBoolean(Value: Boolean);
begin
  GetValue.AsBoolean := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsByte(const Value: TBlobByteData);
begin
  GetValue.AsByte := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsChar(const Value: string);
begin
  SetAsString(Value);
end;

procedure TIfxNativeField.SetAsClob(const Value: IIfxLob);
begin
  GetValue.AsLob := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsCurrency(Value: Currency);
begin
  GetValue.AsCurrency := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsDate(Value: int4);
begin
  GetValue.AsDate := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsDateTime(Value: TDateTime);
begin
  GetValue.AsDateTime := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsDecimal(const Value: TDecimal);
begin
  GetValue.AsDecimal := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsDTime(const Value: TDTime);
begin
  GetValue.AsDTime := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsFloat(Value: Double);
begin
  GetValue.AsFloat := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsInt8(const Value: TIfx_int8);
begin
  GetValue.AsInt8 := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsInteger(Value: int4);
begin
  GetValue.AsInteger := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsInterval(const Value: TIntrvl);
begin
  GetValue.AsInterval := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsLargeint(Value: Largeint);
begin
  GetValue.AsLargeint := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsLocator(Value: PLoc);
begin
  GetValue.AsLocator := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsLVarChar(const Value: string);
begin
  SetAsString(Value);
end;

procedure TIfxNativeField.SetAsMoney(const Value: TDecimal);
begin
  GetValue.AsDecimal := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsNChar(const Value: string);
begin
  SetAsString(Value);
end;

procedure TIfxNativeField.SetAsNVarChar(const Value: string);
begin
  SetAsString(Value);
end;

procedure TIfxNativeField.SetAsOpaque(const Value: string);
begin
  SetAsString(Value);
end;

procedure TIfxNativeField.SetAsSmallFloat(Value: Single);
begin
  GetValue.AsSmallFloat := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsSmallInt(Value: int2);
begin
  GetValue.AsSmallInt := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsSQLTimeStamp(const Value: TSQLTimeStamp);
begin
  GetValue.AsSQLTimeStamp := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsString(const Value: string);
begin
  if Value = '' then
    SetNull else
  begin
    GetValue.AsString := Value;
    NotifyChange;
  end;
end;

procedure TIfxNativeField.SetAsText(const Value: string);
begin
  GetValue.AsString := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsTime(Value: TDateTime);
begin
  GetValue.AsTime := Value;
  NotifyChange;
end;

procedure TIfxNativeField.SetAsVarChar(const Value: string);
begin
  SetAsString(Value);
end;

procedure TIfxNativeField.SetVarValue(const Value: Variant);
begin
  GetValue.AsVariant := Value;
  NotifyChange;
end;

procedure TIfxNativeField.Assign(Source: TPersistent);
begin
  if Source is TIfxNativeField then
    AssignValue(TIfxNativeField(Source)) else
    inherited;
end;

procedure TIfxNativeField.AssignValue(const Value: IIfxValue);
begin
  Value.AssignToValue(Self);
end;

procedure TIfxNativeField.AssignToValue(const Value: IIfxValue);
begin
  ActiveValue.AssignTo(Value);
end;

procedure TIfxNativeField.SaveToStream(Stream: TStream);
begin
  ActiveValue.SaveToStream(Stream);
end;

procedure TIfxNativeField.SaveToFile(const FileName: string);
begin
  ActiveValue.SaveToFile(FileName);
end;

procedure TIfxNativeField.LoadFromStream(Stream: TStream);
begin
  GetValue.LoadFromStream(Stream);
end;

procedure TIfxNativeField.LoadFromFile(const FileName: string);
begin
  GetValue.LoadFromFile(FileName);
end;

procedure TIfxNativeField.CopyValue(const Value: IIfxValue; var Buffer);
begin
  FTempBuffer := @Buffer;
  try
    Value.AssignToValue(Self);
  finally
    FTempBuffer := nil;
  end;
end;


{ TIfxStringField }

constructor TIfxStringField.Create(AOwner: TComponent);
begin
  inherited;
  if Size = 0 then Size := IFX_DEFAULT_STRING_SIZE;
end;

class procedure TIfxStringField.CheckTypeSize(Value: Integer);
begin
  if Value < 0 then
    IDACError(SInvalidFieldSize);
end;

function TIfxStringField.GetDataSize: Integer;
begin
  Result := Size + 1;
end;

function TIfxStringField.GetDefaultWidth: Integer;
begin
  Result := Size;
end;

procedure TIfxStringField.GetText(var Text: string; DisplayText: Boolean);
begin
  if DisplayText and (EditMaskPtr <> '') then
    Text := LXFormatMaskText(EditMaskPtr, GetAsString) else
    Text := GetAsString;
end;

procedure TIfxStringField.SetAsString(const Value: string);
begin
  if TIfxCustomDataSet(DataSet).TrimStrings then
    GetValue.AsString := TrimRight(Value) else
    GetValue.AsString := Value;
  NotifyChange;
end;


{ TIfxCharField }

constructor TIfxCharField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftFixedChar);
end;

function TIfxCharField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxCharValue.Create(Self);
end;


{ TIfxFormatableField }

procedure TIfxFormatableField.SetDisplayFormat(const Value: string);
begin
  if FDisplayFormat <> Value then
  begin
    FDisplayFormat := Value;
    PropertyChanged(False);
  end;
end;

procedure TIfxFormatableField.SetEditFormat(const Value: string);
begin
  if FEditFormat <> Value then
  begin
    FEditFormat := Value;
    PropertyChanged(False);
  end;
end;

procedure TIfxFormatableField.GetText(var Text: string; DisplayText: Boolean);
var
  FmtStr: string;
begin
  if DisplayText or (FEditFormat = '') then
    FmtStr := FDisplayFormat else
    FmtStr := FEditFormat;
  try
    if FmtStr = '' then
      Text := ActiveValue.AsString else
      Text := ActiveValue.Format(FmtStr);
  except
    on E: Exception do
      Text := E.Message;
  end;
end;


{ TIfxNumericField }

constructor TIfxNumericField.Create(AOwner: TComponent);
begin
  inherited;
  Alignment := IFX_DEFAULT_NUMERIC_ALIGNMENT;
end;


{ TIfxSmallIntField }

constructor TIfxSmallIntField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftSmallInt);
  ValidChars := ['+', '-', '0'..'9'];
end;

function TIfxSmallIntField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxSmallIntValue.Create(Self);
end;

function TIfxSmallIntField.GetDefaultWidth: Integer;
begin
  Result := 6;
end;

procedure TIfxSmallIntField.CopyData(Source, Dest: Pointer);
begin
  PInt2(Dest)^ := PInt2(Source)^;
end;


{ TIfxIntegerField }

constructor TIfxIntegerField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftInteger);
  ValidChars := ['+', '-', '0'..'9'];
end;

function TIfxIntegerField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxIntegerValue.Create(Self);
end;

function TIfxIntegerField.GetDefaultWidth: Integer;
begin
  Result := 11;
end;

procedure TIfxIntegerField.CopyData(Source, Dest: Pointer);
begin
  PInt4(Dest)^ := PInt4(Source)^;
end;


{ TIfxFloatField }

constructor TIfxFloatField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftFloat);
  ValidChars := [InformixDecimalSeparator, '+', '-', '0'..'9', 'E', 'e'];
end;

function TIfxFloatField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxFloatValue.Create(Self);
end;

function TIfxFloatField.GetDefaultWidth: Integer;
begin
  Result := 22;
end;

procedure TIfxFloatField.CopyData(Source, Dest: Pointer);
begin
  PDouble(Dest)^ := PDouble(Source)^;
end;


{ TIfxSmallFloatField }

constructor TIfxSmallFloatField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftFloat);
  ValidChars := [InformixDecimalSeparator, '+', '-', '0'..'9', 'E', 'e'];
end;

function TIfxSmallFloatField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxSmallFloatValue.Create(Self);
end;

function TIfxSmallFloatField.GetDefaultWidth: Integer;
begin
  Result := 14;
end;

procedure TIfxSmallFloatField.CopyData(Source, Dest: Pointer);
begin
  PSingle(Dest)^ := PSingle(Source)^;
end;


{ TIfxDecimalField }

constructor TIfxDecimalField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftBCD);
  Size := $10FF;
  ValidChars := [InformixDecimalSeparator, '+', '-', '0'..'9', 'E', 'e'];
end;

function TIfxDecimalField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxDecimalValue.Create(Self);
end;

class procedure TIfxDecimalField.CheckTypeSize(Value: Integer);
var
  Precision, Scale: Integer;
begin
  Precision := PRECTOT(Value);
  if (Precision < 0) or (Precision > 32) then
    IDACErrorFmt(SInvalidFieldPrecision, [Precision]);
  Scale := AdjustScale(PRECDEC(Value), True);
  if (Scale < -1) or (Scale > Precision) then
    IDACErrorFmt(SInvalidFieldScale, [Scale]);
end;

class function TIfxDecimalField.AdjustScale(Value: Integer;
  DisplayValue: Boolean): Integer;
begin
  Result := Value;
  if DisplayValue then
  begin
    if Result = $FF then Result := -1;
  end else
    if Result = -1 then Result := $FF;
end;

function TIfxDecimalField.GetPrecision: Integer;
begin
  Result := PRECTOT(Size);
end;

function TIfxDecimalField.GetScale: Integer;
begin
  Result := AdjustScale(PRECDEC(Size), True);
end;

procedure TIfxDecimalField.SetPrecision(Value: Integer);
begin
  Size := PRECMAKE(Value, PRECDEC(Size));
end;

procedure TIfxDecimalField.SetScale(Value: Integer);
begin
  Size := PRECMAKE(Precision, AdjustScale(Value, False));
end;

function TIfxDecimalField.GetDefaultWidth: Integer;
begin
  Result := Precision + 2;
end;

procedure TIfxDecimalField.CopyData(Source, Dest: Pointer);
begin
  PDecimal(Dest)^ := PDecimal(Source)^;
end;


{ TIfxSerialField }

constructor TIfxSerialField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftAutoInc);
end;


{ TIfxDateField }

constructor TIfxDateField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftDate);
end;

function TIfxDateField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxDateValue.Create(Self);
end;

function TIfxDateField.GetDefaultWidth: Integer;
begin
  Result := 10;
end;

procedure TIfxDateField.CopyData(Source, Dest: Pointer);
begin
  PInt4(Dest)^ := PInt4(Source)^;
end;


{ TIfxMoneyField }

constructor TIfxMoneyField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftCurrency);
end;

function TIfxMoneyField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxMoneyValue.Create(Self);
end;

function TIfxMoneyField.GetDefaultWidth: Integer;
begin
  Result := Precision + 5;
end;

procedure TIfxMoneyField.GetText(var Text: string; DisplayText: Boolean);
var
  FmtStr: string;
begin
  if DisplayText then
    if FDisplayFormat = '' then
      FmtStr := IFX_DEFAULT_MONEY_DISPLAY_FORMAT else
      FmtStr := FDisplayFormat
  else
    if FEditFormat = '' then
      FmtStr := IFX_DEFAULT_MONEY_EDIT_FORMAT else
      FmtStr := FEditFormat;
  try
    if FmtStr = '' then
      Text := ActiveValue.AsString else
      Text := ActiveValue.Format(FmtStr);
  except
    on E: Exception do
      Text := E.Message;
  end;
end;


{ TIfxTimeField }

const
  TimeUnitToInt: array [TIfxTimeUnit] of Integer = (TU_YEAR, TU_MONTH, TU_DAY,
    TU_HOUR, TU_MINUTE, TU_SECOND, TU_F1, TU_F2, TU_F3, TU_F4, TU_F5);

constructor TIfxTimeField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftDateTime);
end;

class procedure TIfxTimeField.CheckTypeSize(Value: Integer);

  procedure CheckUnitRange(TimeUnit: Integer);
  begin
    if (TimeUnit < TU_YEAR) or (TimeUnit > TU_F5) then
      IDACError(SInvalidFieldTimeUnit);
  end;

begin
  CheckUnitRange(TU_START(Value));
  CheckUnitRange(TU_END(Value));
  if TU_START(Value) > TU_END(Value) then
    IDACError(SInvalidFieldTimeUnits);
end;

function TIfxTimeField.GetDefaultWidth: Integer;
begin
  Result := (TU_LEN(Size) * 3) div 2;
end;

function TIfxTimeField.GetFirstUnit: TIfxTimeUnit;
begin
  Result := TIfxTimeUnit(TU_FIELDNO(TU_START(Size)));
end;

function TIfxTimeField.GetLastUnit: TIfxTimeUnit;
begin
  Result := TIfxTimeUnit(TU_FIELDNO(TU_END(Size)));
end;


{ TIfxDateTimeField }

constructor TIfxDateTimeField.Create(AOwner: TComponent);
begin
  inherited;
  Size := TU_DTENCODE(TU_YEAR, TU_F3);
end;

function TIfxDateTimeField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxDTimeValue.Create(Self);
end;

procedure TIfxDateTimeField.CopyData(Source, Dest: Pointer);
begin
  PDTime(Dest)^ := PDTime(Source)^; 
end;

procedure TIfxDateTimeField.SetFirstUnit(const Value: TIfxTimeUnit);
begin
  Size := TU_DTENCODE(TimeUnitToInt[Value], TU_END(Size));
end;

procedure TIfxDateTimeField.SetLastUnit(const Value: TIfxTimeUnit);
begin
  Size := TU_DTENCODE(TU_START(Size), TimeUnitToInt[Value]);
end;


{ TIfxVarCharField }

constructor TIfxVarCharField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftString);
end;

function TIfxVarCharField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxVarCharValue.Create(Self);
end;


{ TIfxIntervalField }

constructor TIfxIntervalField.Create(AOwner: TComponent);
begin
  inherited;
  Size := TU_IENCODE(2, TU_DAY, TU_F3);
end;

function TIfxIntervalField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxIntervalValue.Create(Self);
end;

procedure TIfxIntervalField.CopyData(Source, Dest: Pointer);
begin
  PIntrvl(Dest)^ := PIntrvl(Source)^;
end;

function TIfxIntervalField.GetPrecision: Integer;
begin
  Result := TU_FLEN(Size);
end;

procedure TIfxIntervalField.SetPrecision(const Value: Integer);
begin
  Size := TU_IENCODE(Value, TU_START(Size), TU_END(Size));
end;

procedure TIfxIntervalField.SetFirstUnit(const Value: TIfxTimeUnit);
begin
  Size := TU_IENCODE(TU_FLEN(Size), TimeUnitToInt[Value], TU_END(Size));
end;

procedure TIfxIntervalField.SetLastUnit(const Value: TIfxTimeUnit);
begin
  Size := TU_IENCODE(TU_FLEN(Size), TU_START(Size), TimeUnitToInt[Value]);
end;


{ TIfxNCharField }

function TIfxNCharField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxNCharValue.Create(Self);
end;


{ TIfxNVarCharField }

function TIfxNVarCharField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxNVarCharValue.Create(Self);
end;


{ TIfxInt8Field }

constructor TIfxInt8Field.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftLargeint);
  ValidChars := ['+', '-', '0'..'9'];
end;

function TIfxInt8Field.CreateValue: TIfxFieldValue;
begin
  Result := TIfxInt8Value.Create(Self);
end;

function TIfxInt8Field.GetDefaultWidth: Integer;
begin
  Result := 21;
end;

procedure TIfxInt8Field.CopyData(Source, Dest: Pointer);
begin
  PIfx_int8(Dest)^ := PIfx_int8(Source)^; 
end;


{ TIfxLVarCharField }

function TIfxLVarCharField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxLVarCharValue.Create(Self);
end;


{ TIfxLobField }

procedure TIfxLobField.LoadFromBitmap(Bitmap: TBitmap);
var
  BlobStream: TStream;
begin
  BlobStream := DataSet.CreateBlobStream(Self, bmWrite);
  try
    Bitmap.SaveToStream(BlobStream);
  finally
    BlobStream.Free;
  end;
end;

procedure TIfxLobField.LoadFromStrings(Strings: TStrings);
var
  BlobStream: TStream;
begin
  BlobStream := DataSet.CreateBlobStream(Self, bmWrite);
  try
    Strings.SaveToStream(BlobStream);
  finally
    BlobStream.Free;
  end;
end;

procedure TIfxLobField.SaveToBitmap(Bitmap: TBitmap);
var
  BlobStream: TStream;
begin
  BlobStream := DataSet.CreateBlobStream(Self, bmRead);
  try
    Bitmap.LoadFromStream(BlobStream);
  finally
    BlobStream.Free;
  end;
end;

procedure TIfxLobField.SaveToStrings(Strings: TStrings);
var
  BlobStream: TStream;
begin
  BlobStream := DataSet.CreateBlobStream(Self, bmRead);
  try
    Strings.LoadFromStream(BlobStream);
  finally
    BlobStream.Free;
  end;
end;

procedure TIfxLobField.AssignTo(Dest: TPersistent);
begin
  if Dest is TStrings then
    SaveToStrings(TStrings(Dest))
  else if Dest is TBitmap then
    SaveToBitmap(TBitmap(Dest))
  else if Dest is TPicture then
    SaveToBitmap(TPicture(Dest).Bitmap)
  else
    inherited AssignTo(Dest);
end;

procedure TIfxLobField.CopyData(Source, Dest: Pointer);
begin
  TIfxCustomDataSet(DataSet).LobBufferStrategy.Copy(Source, Dest);
end;

class function TIfxLobField.IsBlob: Boolean;
begin
  Result := True;
end;

procedure TIfxLobField.Assign(Source: TPersistent);
begin
  if Source is TStrings then
    LoadFromStrings(TStrings(Source))
  else if Source is TBitmap then
    LoadFromBitmap(TBitmap(Source))
  else if (Source is TPicture) and (TPicture(Source).Graphic is TBitmap) then
    LoadFromBitmap(TBitmap(TPicture(Source).Graphic))
  else
    inherited;
end;


{ TIfxBlobField }

constructor TIfxBlobField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftOraBlob);
end;

function TIfxBlobField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxBlobValue.Create(Self, TIfxCustomDataSet(DataSet).LobBufferStrategy);
end;

procedure TIfxBlobField.GetText(var Text: string; DisplayText: Boolean);
begin
  Text := '(IfxBlob)';
  if not IsNull then Text := AnsiUpperCase(Text);
end;


{ TIfxClobField } 

constructor TIfxClobField.Create(AOwner: TComponent);
begin
  inherited;
  SetDataType(ftOraClob);
end;

function TIfxClobField.CreateValue: TIfxFieldValue;
begin
  Result := TIfxClobValue.Create(Self, TIfxCustomDataSet(DataSet).LobBufferStrategy);
end;

procedure TIfxClobField.GetText(var Text: string; DisplayText: Boolean);
begin
  Text := '(IfxClob)';
  if not IsNull then Text := AnsiUpperCase(Text);
end;


end.